package org.apache.maven.project.artifact;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.handler.ArtifactHandler;
import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.project.MavenProject;

import java.io.File;
import java.util.Collection;
import java.util.List;

/**
 * Wraps an active project instance to be able to receive updates from its artifact without
 * affecting the original attributes of this artifact.
 *
 * @author <a href="mailto:brett@apache.org">Brett Porter</a>
 * @todo I think this exposes a design flaw in that the immutable and mutable parts of an artifact
 *       are in one class and should be split. ie scope, file, etc depend on the context of use,
 *       whereas everything else is immutable.
 */
@Deprecated
public class ActiveProjectArtifact implements Artifact {
  private final Artifact artifact;

  private final MavenProject project;

  public ActiveProjectArtifact(MavenProject project, Artifact artifact) {
    this.artifact = artifact;
    this.project = project;

    artifact.setFile(project.getArtifact().getFile());
    artifact.setResolved(true);
  }

  /** {@inheritDoc} */
  public File getFile() {
    // we need to get the latest file for the project, not the artifact that was created at one
    // point in time
    return project.getArtifact().getFile();
  }

  /** {@inheritDoc} */
  public String getGroupId() {
    return artifact.getGroupId();
  }

  /** {@inheritDoc} */
  public String getArtifactId() {
    return artifact.getArtifactId();
  }

  /** {@inheritDoc} */
  public String getVersion() {
    return artifact.getVersion();
  }

  /** {@inheritDoc} */
  public void setVersion(String version) {
    artifact.setVersion(version);
  }

  /** {@inheritDoc} */
  public String getScope() {
    return artifact.getScope();
  }

  /** {@inheritDoc} */
  public String getType() {
    return artifact.getType();
  }

  /** {@inheritDoc} */
  public String getClassifier() {
    return artifact.getClassifier();
  }

  /** {@inheritDoc} */
  public boolean hasClassifier() {
    return artifact.hasClassifier();
  }

  /** {@inheritDoc} */
  public void setFile(File destination) {
    artifact.setFile(destination);
    project.getArtifact().setFile(destination);
  }

  /** {@inheritDoc} */
  public String getBaseVersion() {
    return artifact.getBaseVersion();
  }

  /** {@inheritDoc} */
  public void setBaseVersion(String baseVersion) {
    artifact.setBaseVersion(baseVersion);
  }

  /** {@inheritDoc} */
  public String getId() {
    return artifact.getId();
  }

  /** {@inheritDoc} */
  public String getDependencyConflictId() {
    return artifact.getDependencyConflictId();
  }

  /** {@inheritDoc} */
  public void addMetadata(ArtifactMetadata metadata) {
    artifact.addMetadata(metadata);
  }

  /** {@inheritDoc} */
  public Collection<ArtifactMetadata> getMetadataList() {
    return artifact.getMetadataList();
  }

  /** {@inheritDoc} */
  public void setRepository(ArtifactRepository remoteRepository) {
    artifact.setRepository(remoteRepository);
  }

  /** {@inheritDoc} */
  public ArtifactRepository getRepository() {
    return artifact.getRepository();
  }

  /** {@inheritDoc} */
  public void updateVersion(String version, ArtifactRepository localRepository) {
    artifact.updateVersion(version, localRepository);
  }

  /** {@inheritDoc} */
  public String getDownloadUrl() {
    return artifact.getDownloadUrl();
  }

  /** {@inheritDoc} */
  public void setDownloadUrl(String downloadUrl) {
    artifact.setDownloadUrl(downloadUrl);
  }

  /** {@inheritDoc} */
  public ArtifactFilter getDependencyFilter() {
    return artifact.getDependencyFilter();
  }

  /** {@inheritDoc} */
  public void setDependencyFilter(ArtifactFilter artifactFilter) {
    artifact.setDependencyFilter(artifactFilter);
  }

  /** {@inheritDoc} */
  public ArtifactHandler getArtifactHandler() {
    return artifact.getArtifactHandler();
  }

  /** {@inheritDoc} */
  public List<String> getDependencyTrail() {
    return artifact.getDependencyTrail();
  }

  /** {@inheritDoc} */
  public void setDependencyTrail(List<String> dependencyTrail) {
    artifact.setDependencyTrail(dependencyTrail);
  }

  /** {@inheritDoc} */
  public void setScope(String scope) {
    artifact.setScope(scope);
  }

  /** {@inheritDoc} */
  public VersionRange getVersionRange() {
    return artifact.getVersionRange();
  }

  /** {@inheritDoc} */
  public void setVersionRange(VersionRange newRange) {
    artifact.setVersionRange(newRange);
  }

  /** {@inheritDoc} */
  public void selectVersion(String version) {
    artifact.selectVersion(version);
  }

  /** {@inheritDoc} */
  public void setGroupId(String groupId) {
    artifact.setGroupId(groupId);
  }

  /** {@inheritDoc} */
  public void setArtifactId(String artifactId) {
    artifact.setArtifactId(artifactId);
  }

  /** {@inheritDoc} */
  public boolean isSnapshot() {
    return artifact.isSnapshot();
  }

  /** {@inheritDoc} */
  public int compareTo(Artifact a) {
    return artifact.compareTo(a);
  }

  /** {@inheritDoc} */
  public void setResolved(boolean resolved) {
    artifact.setResolved(resolved);
  }

  /** {@inheritDoc} */
  public boolean isResolved() {
    return artifact.isResolved();
  }

  /** {@inheritDoc} */
  public void setResolvedVersion(String version) {
    artifact.setResolvedVersion(version);
  }

  /** {@inheritDoc} */
  public void setArtifactHandler(ArtifactHandler handler) {
    artifact.setArtifactHandler(handler);
  }

  /** {@inheritDoc} */
  public String toString() {
    return "active project artifact:\n\tartifact = " + artifact + ";\n\tproject: " + project;
  }

  /** {@inheritDoc} */
  public boolean isRelease() {
    return artifact.isRelease();
  }

  /** {@inheritDoc} */
  public void setRelease(boolean release) {
    artifact.setRelease(release);
  }

  /** {@inheritDoc} */
  public List<ArtifactVersion> getAvailableVersions() {
    return artifact.getAvailableVersions();
  }

  /** {@inheritDoc} */
  public void setAvailableVersions(List<ArtifactVersion> versions) {
    artifact.setAvailableVersions(versions);
  }

  /** {@inheritDoc} */
  public boolean isOptional() {
    return artifact.isOptional();
  }

  /** {@inheritDoc} */
  public ArtifactVersion getSelectedVersion() throws OverConstrainedVersionException {
    return artifact.getSelectedVersion();
  }

  /** {@inheritDoc} */
  public boolean isSelectedVersionKnown() throws OverConstrainedVersionException {
    return artifact.isSelectedVersionKnown();
  }

  /** {@inheritDoc} */
  public void setOptional(boolean optional) {
    artifact.setOptional(optional);
  }

  /** {@inheritDoc} */
  public int hashCode() {
    int result = 17;

    result = 37 * result + getGroupId().hashCode();
    result = 37 * result + getArtifactId().hashCode();
    result = 37 * result + getType().hashCode();
    if (getVersion() != null) {
      result = 37 * result + getVersion().hashCode();
    }
    result = 37 * result + (getClassifier() != null ? getClassifier().hashCode() : 0);

    return result;
  }

  /** {@inheritDoc} */
  public boolean equals(Object o) {
    if (o == this) {
      return true;
    }

    if (!(o instanceof Artifact)) {
      return false;
    }

    Artifact a = (Artifact) o;

    if (!a.getGroupId().equals(getGroupId())) {
      return false;
    } else if (!a.getArtifactId().equals(getArtifactId())) {
      return false;
    } else if (!a.getVersion().equals(getVersion())) {
      return false;
    } else if (!a.getType().equals(getType())) {
      return false;
    } else if (a.getClassifier() == null ? getClassifier() != null : !a.getClassifier().equals(getClassifier())) {
      return false;
    }

    return true;
  }

}
